package event

import (
	"sync"

	"gitee.com/shoyer/logger"
)

var (
	lock      sync.RWMutex
	listeners = make(map[Event][]interface{})
)

// Emit 发送事件
func Emit(e Event, data EventData) {
	emit(e, data, false)
}

// Emit 发送事件, 但会等事件handler执行完成，即在同一个协程完成，不会开新协程
func EmitSync(e Event, data EventData) {
	emit(e, data, true)
}

func emit(e Event, data EventData, sync bool) {
	if handlers, ok := listeners[e]; ok {
		for _, h := range handlers {
			hit := false

			if hh, ok := h.(func(Event string, data EventData)); ok {
				if sync {
					hh(e, data)
				} else {
					go hh(e, data)
				}

				hit = true
			}

			if hh, ok := h.(*EventHandler); ok {
				if sync {
					(*hh)(e, data)
				} else {
					go (*hh)(e, data)
				}

				hit = true
			}

			if hh, ok := h.(Handler); ok {
				if sync {
					hh.EventHandler(e, data)
				} else {
					go hh.EventHandler(e, data)
				}
				hit = true
			}

			if !hit {
				logger.Errorf("event handler not matched: %s", e)
			}
		}
	}
}

// On 注册事件
// h *EventHandler || *Handler
func On(e Event, h interface{}) {
	if h == nil {
		return
	}

	handlers := listeners[e]
	for _, v := range handlers {
		if v == h {
			// 已经注册过，同一个事件，同一个处理器，只注册一次，重复注册只生效一个。
			return
		}
	}

	lock.Lock()
	defer lock.Unlock()

	handlers = append(handlers, h)
	listeners[e] = handlers
}

// Off 移除事件
func Off(e Event, h interface{}) {
	if h == nil {
		return
	}

	if handlers, ok := listeners[e]; ok {
		for i, hh := range handlers {
			if hh == h {
				lock.Lock()
				listeners[e] = append(listeners[e][:i], listeners[e][i+1:]...)
				lock.Unlock()
				break
			}
		}
	}
}
